package com.mdhw.config;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mdhw.system.entity.SysRegion;
import com.mdhw.system.vo.SysRegionTree;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPoolConfig;

import java.time.Duration;
import java.util.List;

@Configuration
@EnableCaching
public class RedisConfigs {

    @Value("${spring.redis.database}")
    private int databaseUser;

    private static Integer databaseCompany = 12;
    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.password}")
    private String password;
    @Value("${spring.redis.port}")
    private int port;
    @Value("${spring.redis.timeout}")
    private long timeout;
    @Value("${spring.redis.jedis.pool.max-idle}")
    private int maxIdle;
    @Value("${spring.redis.jedis.pool.min-idle}")
    private int minIdle;
    @Value("${spring.redis.jedis.pool.max-active}")
    private int maxActive;
    @Value("${spring.redis.jedis.pool.max-wait}")
    private long maxWait;


    @Bean(name={"redisTemplateUser"})//容器注入名称
    public RedisTemplate<String, Object> redisTemplateUser() {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisUserConnectionFactory());
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer(om);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer();
        // ------------ 如果需要直接反序列化 对于kotlin中的类必须是open class 否则会没有@class -------------
        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // value序列化方式采用jackson
        template.setValueSerializer(jdkSerializationRedisSerializer);
        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(jdkSerializationRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }


    @Bean(name={"redisTemplateCompany"})//容器注入名称
    public RedisTemplate<String, Object> redisTemplateCompany() {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisCompanyConnectionFactory());
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer(om);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer();
        // ------------ 如果需要直接反序列化 对于kotlin中的类必须是open class 否则会没有@class -------------
        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // value序列化方式采用jackson
        template.setValueSerializer(jdkSerializationRedisSerializer);
        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(jdkSerializationRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }
    private JedisConnectionFactory redisUserConnectionFactory() {
        RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
        redisStandaloneConfiguration.setDatabase(databaseUser);
        redisStandaloneConfiguration.setHostName(host);
        redisStandaloneConfiguration.setPort(port);
        redisStandaloneConfiguration.setPassword(RedisPassword.of(password));
        JedisClientConfiguration clientConfig = JedisClientConfiguration.builder()
                .connectTimeout(Duration.ofMillis(timeout))
                .usePooling()
                .poolConfig(jedisPoolConfig())
                .build();
        JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(redisStandaloneConfiguration,clientConfig);
        jedisConnectionFactory.afterPropertiesSet();
        return jedisConnectionFactory;
    }

    private JedisConnectionFactory redisCompanyConnectionFactory() {
        RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
        redisStandaloneConfiguration.setDatabase(databaseCompany);
        redisStandaloneConfiguration.setHostName(host);
        redisStandaloneConfiguration.setPort(port);
        redisStandaloneConfiguration.setPassword(RedisPassword.of(password));
        JedisClientConfiguration clientConfig = JedisClientConfiguration.builder()
                .connectTimeout(Duration.ofMillis(timeout))
                .usePooling()
                .poolConfig(jedisPoolConfig())
                .build();
        JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(redisStandaloneConfiguration,clientConfig);
        jedisConnectionFactory.afterPropertiesSet();
        return jedisConnectionFactory;
    }
    /**
     * jedis连接池配置
     */
    private JedisPoolConfig jedisPoolConfig() {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxIdle(maxIdle);
        jedisPoolConfig.setMaxTotal(maxActive);
        jedisPoolConfig.setMaxWaitMillis(maxWait);
        jedisPoolConfig.setMinIdle(minIdle);
        return jedisPoolConfig;
    }

    public static void main(String[] args) {
        String str = "[{\"children\":[{\"children\":[{\"code\":\"110101\",\"id\":376,\"name\":\"东城区\",\"pid\":32,\"price\":600.00,\"revision\":0,\"sortNum\":0,\"status\":\"1\",\"type\":3,\"updateDate\":1728727965000},{\"code\":\"110102\",\"id\":377,\"name\":\"西城区\",\"pid\":32,\"price\":600.00,\"revision\":0,\"sortNum\":0,\"status\":\"1\",\"type\":3,\"updateDate\":1728727965000},{\"code\":\"110105\",\"id\":378,\"name\":\"朝阳区\",\"pid\":32,\"price\":600.00,\"revision\":0,\"sortNum\":0,\"status\":\"1\",\"type\":3},{\"code\":\"110106\",\"id\":379,\"name\":\"丰台区\",\"pid\":32,\"price\":600.00,\"revision\":0,\"sortNum\":0,\"status\":\"1\",\"type\":3,\"updateDate\":1728727965000},{\"code\":\"110107\",\"id\":380,\"name\":\"石景山区\",\"pid\":32,\"price\":600.00,\"revision\":0,\"sortNum\":0,\"status\":\"1\",\"type\":3,\"updateDate\":1728727965000},{\"code\":\"110108\",\"id\":381,\"name\":\"海淀区\",\"pid\":32,\"price\":600.00,\"revision\":0,\"sortNum\":0,\"status\":\"1\",\"type\":3,\"updateDate\":1728727965000},{\"code\":\"110109\",\"id\":382,\"name\":\"门头沟区\",\"pid\":32,\"price\":600.00,\"revision\":0,\"sortNum\":0,\"status\":\"1\",\"type\":3,\"updateDate\":1728727965000},{\"code\":\"110111\",\"id\":383,\"name\":\"房山区\",\"pid\":32,\"price\":600.00,\"revision\":0,\"sortNum\":0,\"status\":\"1\",\"type\":3,\"updateDate\":1728727965000},{\"code\":\"110112\",\"id\":384,\"name\":\"通州区\",\"pid\":32,\"price\":600.00,\"revision\":0,\"sortNum\":0,\"status\":\"1\",\"type\":3,\"updateDate\":1728727965000},{\"code\":\"110113\",\"id\":385,\"name\":\"顺义区\",\"pid\":32,\"price\":600.00,\"revision\":0,\"sortNum\":0,\"status\":\"1\",\"type\":3,\"updateDate\":1728727965000},{\"code\":\"110114\",\"id\":386,\"name\":\"昌平区\",\"pid\":32,\"price\":600.00,\"revision\":0,\"sortNum\":0,\"status\":\"1\",\"type\":3,\"updateDate\":1728727965000},{\"code\":\"110115\",\"id\":387,\"name\":\"大兴区\",\"pid\":32,\"price\":600.00,\"revision\":0,\"sortNum\":0,\"status\":\"1\",\"type\":3,\"updateDate\":1728727965000},{\"code\":\"110116\",\"id\":388,\"name\":\"怀柔区\",\"pid\":32,\"price\":600.00,\"revision\":0,\"sortNum\":0,\"status\":\"1\",\"type\":3,\"updateDate\":1728727965000},{\"code\":\"110117\",\"id\":389,\"name\":\"平谷区\",\"pid\":32,\"price\":600.00,\"revision\":0,\"sortNum\":0,\"status\":\"1\",\"type\":3,\"updateDate\":1728727965000},{\"code\":\"110118\",\"id\":390,\"name\":\"密云区\",\"pid\":32,\"price\":600.00,\"revision\":0,\"sortNum\":0,\"status\":\"1\",\"type\":3,\"updateDate\":1728727965000},{\"code\":\"110119\",\"id\":391,\"name\":\"延庆区\",\"pid\":32,\"price\":600.00,\"revision\":0,\"sortNum\":0,\"status\":\"1\",\"type\":3,\"updateDate\":1728727965000}],\"code\":\"110100\",\"id\":32,\"name\":\"市辖区\",\"pid\":1,\"price\":600.00,\"revision\":0,\"sortNum\":0,\"status\":\"1\",\"type\":2,\"updateDate\":1727145751000,\"updateUser\":\"admin\"}],\"code\":\"110000\",\"id\":1,\"name\":\"北京市\",\"pid\":0,\"price\":0.00,\"revision\":0,\"sortNum\":0,\"status\":\"1\",\"type\":1}]";
        List<SysRegionTree> sysRegionTreeList = JSONObject.parseArray(str, SysRegionTree.class);
        System.out.println(JSONObject.toJSONString(sysRegionTreeList));
    }

}
